<?php

namespace common\base;

use Yii;

/**
 * 扩展Yii2 自带加密解密处理
 *
 * @author emhome<emhome@163.com>
 * @since 2.0
 */
class Security extends \yii\base\Security {

    public $public_key = null;
    public $secret_key = null;

    /**
     * 加密
     * @param mixed $data 待加密数据
     * @param string $key 密钥
     * @return string base64_encode字符串
     */
    public function encryptMaster($data, $key = false) {
        if ($key === false) {
            $key = $this->generatePrivateKey($key);
        }
        $encryptByKey = $this->encryptByKey($data, $key, $this->public_key);
        return base64_encode($encryptByKey);
    }

    /**
     * 解密
     * @param string $data 待解密数据
     * @param string $key 密钥
     * @return mixed
     */
    public function decryptMaster($data, $key = false) {
        if ($key === false) {
            $key = $this->generatePrivateKey($key);
        }
        return $this->decryptByKey(base64_decode($data), $key, $this->public_key);
    }

    /**
     * 自定义加密
     * @param string $data 待解密数据
     * @param string $key 密钥
     * @return mixed
     */
    public function generatePrivateKey($data = false) {
        if ($data === false) {
            $data = md5($this->public_key);
        }
        $data_md5 = md5($data);
        $figure = preg_replace('/\D/s', '', $data_md5);
        $mlen = str_split($figure);
        $pos = array_sum($mlen) % 32 - 1;
        $string = '';
        foreach (str_split($data_md5) as $key => $char) {
            $string .= $char;
            if ($key == $pos) {
                $string .= $this->public_key;
            }
        }
        return md5($string);
    }

    /**
     * APP数据安全加密
     * @param string $data 待加密数据
     * @param string $key 密钥
     * @return mixed
     */
    public function encryptDataByKey($data, $key = null) {
        if ($key === null) {
            $key = $this->secret_key;
        }
        list($blockSize, $keySize) = $this->allowedCiphers[$this->cipher];
        if (strlen($key) !== $keySize) {
            return false;
        }
        $pos = rand(0, $keySize);
        $iv = substr($key . $key, $pos, $blockSize);
        $prefix = chr($pos + 48);
        $encrypt_data = openssl_encrypt($data, $this->cipher, $key, OPENSSL_RAW_DATA, $iv);
        return base64_encode($prefix . base64_encode($encrypt_data));
    }

    /**
     * APP安全数据解密
     * @param string $data 待解密数据
     * @param string $key 密钥
     * @return mixed
     */
    public function decryptDataByKey($data, $key = null) {
        if ($key === null) {
            $key = $this->secret_key;
        }
        list($blockSize, $keySize) = $this->allowedCiphers[$this->cipher];
        if (strlen($key) !== $keySize) {
            return false;
        }
        $content = base64_decode($data);
        $pos = ord(substr($content, 0, 1)) - 48;
        $encrypt_data = base64_decode(substr($content, 1));
        $iv = substr($key . $key, $pos, $blockSize);
        return openssl_decrypt($encrypt_data, $this->cipher, $key, OPENSSL_RAW_DATA, $iv);
    }

}
